package com.joysuch.wwyt.mh.storage.impl;

import com.google.common.collect.Lists;
import com.joysuch.wwyt.bp.repository.BpEnterpriseInfoDao;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.mh.entity.MhAlarmLimitConfig;
import com.joysuch.wwyt.mh.service.MhAlarmLevelConfigService;
import com.joysuch.wwyt.mh.service.MhAlarmLimitConfigService;
import com.joysuch.wwyt.mh.storage.MonitorPointData;
import com.joysuch.wwyt.mh.storage.IMonitorPointDataHandler;
import com.joysuch.wwyt.mh.storage.IMonitorPointDataStorage;
import com.joysuch.wwyt.risk.entity.RiskEvaluationControl;
import com.joysuch.wwyt.risk.repository.RiskEvaluationControlDao;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.util.NamedThreadFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author qingzhou
 * 2019-11-20
 */
@Slf4j
@Component("defaultIMonitorPointDataHandler")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DefaultIMonitorPointDataHandler implements IMonitorPointDataHandler {

    private final IMonitorPointDataStorage IMonitorPointDataStorage;

    private List<IMonitorPointDataHandler> bizHandler = Lists.newArrayList();

    private final int corePoolSize = 5;
    private final int maxPoolSize = 50;

    @Resource
    private MhAlarmLevelConfigService mhAlarmLevelConfigService;

    @Resource
    private MhAlarmLimitConfigService mhAlarmLimitConfigService;

    @Autowired
    private BpEnterpriseInfoDao enterpriseInfoDao;

    @Autowired
    private BaseConfigService baseConfigService;

    @Autowired
    private RiskEvaluationControlDao riskEvaluationControlDao;

    private final ThreadPoolExecutor bizExecutor =
            new ThreadPoolExecutor(corePoolSize, maxPoolSize, 10, TimeUnit.MINUTES,
                    new LinkedBlockingQueue<>(10000),
                    new NamedThreadFactory("monitor-point-biz-handler"),
                    (r, executor) ->
                            log.error("monitor-point-biz-handler thread pool is EXHAUSTED. " +
                                    "core pool size {} max pool size {}", corePoolSize, maxPoolSize));

    private final ThreadPoolExecutor storeExecutor =
            new ThreadPoolExecutor(corePoolSize, maxPoolSize, 10, TimeUnit.MINUTES,
                    new LinkedBlockingQueue<>(10000),
                    new NamedThreadFactory("monitor-point-store-handler"),
                    (r, executor) ->
                            log.error("monitor-point-store-handler thread pool is EXHAUSTED. " +
                                    "core pool size {} max pool size {}", corePoolSize, maxPoolSize));

    void registerHandler(@NotNull IMonitorPointDataHandler handler) {
        bizHandler.add(handler);
    }

    @Override
    public void handle(List<MonitorPointData> list,Map<String, MhAlarmLimitConfig> configMap,Map<String,Map<Integer,String>> levelMaps,
                       BaseConfig switchConfig,Map<String, RiskEvaluationControl> dyContMap) {
        storeExecutor.execute(() -> IMonitorPointDataStorage.store(list));

        List<Map<String, Object>> tenentIdAndOrgCode = enterpriseInfoDao.selectTenentIdAndOrgCodes();
        tenentIdAndOrgCode.forEach(t -> {
            Long tenantId = ((BigInteger) t.get("tenentId")).longValue();
            String orgCode = (String) t.get("orgCode");
            MhAlarmLimitConfig config = mhAlarmLimitConfigService.findOneConfig(tenantId,orgCode);
            configMap.put(tenantId+"_"+orgCode,config);
            Map<Integer,String> levelMap = mhAlarmLevelConfigService.findLevelMap(tenantId,orgCode);
            levelMaps.put(tenantId+"_"+orgCode,levelMap);
            //动态风险
            RiskEvaluationControl dyCont = riskEvaluationControlDao.findByNameAndOrgCodeAndTenentId("动态安全风险评估", orgCode.substring(0, 7), tenantId);
            dyContMap.put(tenantId+"_"+orgCode,dyCont);
        });
        switchConfig = baseConfigService.getBaseConfigFromRedis(BaseConfigCodes.OPEN_GRADE_ALARM);
        BaseConfig finalSwitchConfig = switchConfig;
        bizHandler.forEach(h -> bizExecutor.execute(() -> h.handle(list, configMap, levelMaps, finalSwitchConfig,dyContMap)));
    }

}